<?php
declare(strict_types=1);


namespace UU\Suite\DingTalk;

use Psr\Http\Message\ServerRequestInterface;
use UU\Suite\DingTalk\Traits\InteractWithJsonMessage;
use UU\Suite\Kernel\Contracts\EncryptorInterface;
use UU\Suite\Kernel\Contracts\ServerInterface;
use UU\Suite\Kernel\Message;
use UU\Suite\Kernel\Traits\InteractsWithCache;
use UU\Suite\Kernel\Traits\InteractWithHandlers;

class Server implements ServerInterface
{
    use InteractWithHandlers;
    use InteractWithJsonMessage;
    use InteractsWithCache;
    /**
     * @var ServerRequestInterface
     */
    protected $request;
    /**
     * @var EncryptorInterface
     */
    protected $encryptor;

    /**
     * @throws \Throwable
     */
    public function __construct(
        ServerRequestInterface $request,
        ?EncryptorInterface $encryptor
    )
    {
        $this->request = $request;
        $this->encryptor = $encryptor;
    }

    /**
     * @param callable|string $handler
     * @return $this
     */
    // 成员变更通知 + 部门变更通知 + 标签变更通知
    public function handleContactChanged($handler): self
    {
        $this->with(
            function (Message $message, \Closure $next) use ($handler) {
                return $message->EventType === 'org_dept_modify' ? $handler($message) : $next($message);
            }
        );

        return $this;
    }

    /**
     * @param callable|string $handler
     * @return $this
     */
    public function handleUserTagUpdated($handler): self
    {
        $this->with(
            function (Message $message, \Closure $next) use ($handler) {
                return
                    $message->Event === 'change_contact' && $message->ChangeType === 'update_tag' ? $handler($message) : $next($message);
            }
        );

        return $this;
    }

    /**
     * @param callable|string $handler
     * @return $this
     */
    public function handleUserCreated($handler): self
    {
        $this->with(
            function (Message $message, \Closure $next) use ($handler) {
                return
                    $message->Event === 'change_contact' && $message->ChangeType === 'create_user' ? $handler($message) : $next($message);
            }
        );

        return $this;
    }

    /**
     * @param callable|string $handler
     * @return $this
     */
    public function handleUserUpdated($handler): self
    {
        $this->with(
            function (Message $message, \Closure $next) use ($handler) {
                return
                    $message->Event === 'change_contact' && $message->ChangeType === 'update_user' ? $handler($message) : $next($message);
            }
        );

        return $this;
    }

    /**
     * @param callable|string $handler
     * @return $this
     */
    public function handleUserDeleted($handler): self
    {
        $this->with(
            function (Message $message, \Closure $next) use ($handler) {
                return
                    $message->Event === 'change_contact' && $message->ChangeType === 'delete_user' ? $handler($message) : $next($message);
            }
        );

        return $this;
    }

    /**
     * @param callable|string $handler
     * @return $this
     */
    public function handlePartyCreated($handler): self
    {
        $this->with(
            function (Message $message, \Closure $next) use ($handler) {
                return
                    $message->InfoType === 'change_contact' && $message->ChangeType === 'create_party' ? $handler($message) : $next($message);
            }
        );

        return $this;
    }

    /**
     * @param callable|string $handler
     * @return $this
     */
    public function handlePartyUpdated($handler): self
    {
        $this->with(
            function (Message $message, \Closure $next) use ($handler) {
                return
                    $message->InfoType === 'change_contact' && $message->ChangeType === 'update_party' ? $handler($message) : $next($message);
            }
        );

        return $this;
    }

    /**
     * @param callable|string $handler
     * @return $this
     */
    public function handlePartyDeleted($handler): self
    {
        $this->with(
            function (Message $message, \Closure $next) use ($handler) {
                return
                    $message->InfoType === 'change_contact' && $message->ChangeType === 'delete_party' ? $handler($message) : $next($message);
            }
        );

        return $this;
    }

    /**
     * @param callable|string $handler
     * @return $this
     */
    public function handleBatchJobsFinished($handler): self
    {
        $this->with(
            function (Message $message, \Closure $next) use ($handler) {
                return
                    $message->Event === 'batch_job_result' ? $handler($message) : $next($message);
            }
        );

        return $this;
    }
}